// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

#ifndef _BFILTER_H_
#define _BFILTER_H_

#include "bmapfile.h"
#include "chromosomes.h"
#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*!
\file
\ingroup	gio
\brief		Parrellised Filtering Functions 
\details 
	File contains are series of SNP/Person filters to remove noise 
	from a genomic data-set.<br>
	The filters are probability or category data removal operations
	based on the C++ filter code of PLINK.<br>
	This code is used by a multi-core MPI filter programme (see \ref pformat_main) which applies the filters 
	in the following order:-<br>
	-# Person Removal = Category
	-# Person Removal = Missingness
	-# SNP Removal = Missingness
	-# SNP Removal = Major Allelic Frequency
	-# SNP Removal = Hardy-Weinburg Equilibrium
	
	The filters 2-4 are mandatory and the filters 1 &amp; 5 are optional.<br>
	Each filter populates 2 boolean arrays (SNP and Person) which are used to flag
	that a data element is to be removed from an analysis data-set.<br>
	Each numeric filter has an associated threshold value of 0.0 to 1.0.<br>
	Filter threshold values are bound to the structure \ref selected_options and 
	initialised with a default value.<br>
	When a SNP is removed from a data-set due to particular filter, the removal reason is recorded 
	by using constant value defined in this header file.
*/

/*! \brief No reason for SNP/Person removal */
#define FILTER_REASON_NOTHING 0

/*! 
\brief Person removal due to missingness
\details PLINK MIND parameter
\see selected_options::MAX_IND_MISSING
\see DEFAULT_MIND
*/
#define FILTER_REASON_PERSON_MISSINGNESS 1

/*! 
\brief SNP removal due to missingness
\details PLINK GENO parameter
\see selected_options::MAX_GENO_MISSING
\see DEFAULT_GENO
*/
#define FILTER_REASON_SNP_MISSINGNESS 2

/*! 
\brief SNP removal due to Major Allelic Frequency.
\details PLINK MAF parameter
\see selected_options::MAX_GENO_MISSING
\see DEFAULT_MAF
*/
#define FILTER_REASON_SNP_MAF 4

/*! 
\brief SNP removal due to Hardy-Weinburg Equilibrium.
\details PLINK HWE parameter
\see selected_options::HWD_limit
\see DEFAULT_HWE_LIMIT
*/
#define FILTER_REASON_SNP_HWE 8

/*!
\brief Parse exclusion list to apply a category filter.
\details
	Function parses a text file containing a list of integers.<br>
	These numbers are indices of people to be removed from the analysis sample array.<br>
	One number per line with the reference in the 'persons_to_del' array is set to TRUE
	if that person is to be removed from an analysis data-set.<br>
	If an index in the text file is out of range, it simply gets ignored.<br>
	The path to the input text file bound to the variable \ref selected_options::szExcludeListFileName.
\param [in] ops Location of the input file (see \ref selected_options::szExcludeListFileName)
\param [in] nSamples Number of people/samples in an analysis data-set.
\param [in, out] persons_to_del Array of 'Person to Delete' flags
\returns 1 if successful, 0 on failure
*/
int bfilter_parse_exclude_list(struct selected_options *ops, int nSamples, BOOL *persons_to_del);

/*!
\brief Apply Person Missingness filter to an analysis data-set.
\details
	Applies a missingness index threshold to an analysis data-set to 
	remove people from the sample array.<br>
	The SNP missingness of each person is loaded from file
	and stored in an array.<br>
	A reference in the 'persons_to_del' array is set to TRUE
	if that person is to be removed from an analysis data-set.<br>
	The missingness threshold is bound to the variable \ref selected_options::MAX_IND_MISSING .<br>
	If the \ref selected_options::MAX_IND_MISSING is set as 1.0, this filter is not applied.
\param [in] nSamples Number of people/samples in an analysis data-set.
\param [in] missingness Array containing SNP missingness per person.
\param [in, out] persons_to_del Array of 'Person to Delete' flags
\param [in] ops Filter thresholds (\ref selected_options::MAX_IND_MISSING) 
\see missingnessfile.h
*/
int bfilter_person_do_mind(int nSamples, double *missingness, BOOL *persons_to_del, struct selected_options *ops);

/*!
\brief Apply Major Allelic Frequency (MAF) and Missingness Filters (GENO) to SNPs of a data-set.
\details
	If a SNP is to be removed then the value in the array 'snps_to_del' is set to TRUE.<br>
	If a SNP is removed from a data-set, the reason why and any associated test statistic 
	are stored in an arrays passed to this function.<br>
	The MAF threshold value is bound to variable \ref selected_options::min_af.<br>
	The GENO threshold value is bound to the variable \ref selected_options::MAX_GENO_MISSING.<br>
	Setting the \ref selected_options::min_af or \ref selected_options::MAX_GENO_MISSING 
	threshold values to 1.0 means these filters will not be applied.
\param [in] bpedData Fragment of allelic data to apply the MAF/GENO filters
\param [in] snps SNP listing of alleles in the analysis data
\param [in] nSNPs Number of SNPs being analysis data-set
\param [in, out] snps_to_del Array of 'SNPs to Delete' flags 
\param [in, out] snps_reasons_to_del Reasons why SNP was removed (\ref FILTER_REASON_SNP_MISSINGNESS or \ref FILTER_REASON_SNP_MAF)
\param [in, out] snp_del_stats Value of a test statistic which removed a SNP from a data-set.
\param [in] nSamples No. Sample/People in a data-set
\param [in] persons_to_del Array of 'Person to Delete' flags
\param [in] sex Gender of people (male = TRUE, female = FALSE)
\param [in] founders Flag if person to be included in the analysis (PLINK artifact for parental relationship, all set to TRUE)
\param [in] chromos Human chromosomal model
\param [in] ops Filter threshold values (\ref selected_options::min_af and \ref selected_options::MAX_GENO_MISSING)
*/
int bfilter_snp_do_maf_and_mind(char *bpedData, struct small_locus *snps, int nSNPs, BOOL *snps_to_del, char *snps_reasons_to_del, double *snp_del_stats, int nSamples, BOOL *persons_to_del, BOOL *sex, BOOL *founders, struct chromosomes *chromos, struct selected_options *ops);

/*!
\brief Apply Hardy-Weinburg Equilibrium (HWE) filter to SNPs of a data-set.
\details
	If a SNP is to be removed then the value in the array 'snps_to_del' is set to TRUE.<br>
	If a SNP is removed from a data-set, the reason why and any associated test statistic 
	are stored in an arrays passed to this function.<br>
	The HWE threshold value is bound to variable \ref selected_options::HWD_limit.<br>
	The version of the HWE depends on whether values in the phenotype are of a binary or quantitative trait
	as indicated by the \ref selected_options::bt and \ref selected_options::qt status flags.
\param [in] bpedData Fragment of allelic data to apply the MAF/GENO filters
\param [in] snps SNP listing of alleles in the analysis data
\param [in] nSNPs Number of SNPs being analysis data-set
\param [in, out] snps_to_del Array of 'SNPs to Delete' flags 
\param [in, out] snps_reasons_to_del Reasons why SNP was removed (\ref FILTER_REASON_SNP_MISSINGNESS or \ref FILTER_REASON_SNP_MAF)
\param [in, out] snp_del_stats Value of a test statistic which removed a SNP from a data-set.
\param [in] nSamples No. Sample/People in a data-set
\param [in] persons_to_del Array of 'Person to Delete' flags
\param [in] sex Gender of people (male = TRUE, female = FALSE)
\param [in] founders Flag if person to be included in the analysis (PLINK artifact for parental relationship, all set to TRUE)
\param [in] phe_values Phenotype values of the sample response variable
\param [in] chromos Human chromosomal model
\param [in] ops Filter threshold values (\ref selected_options::min_af and \ref selected_options::MAX_GENO_MISSING)
*/
int bfilter_snp_do_hwe(char *bpedData, struct small_locus *snps, int nSNPs, BOOL *snps_to_del, char *snps_reasons_to_del, double *snp_del_stats, int nSamples, BOOL *persons_to_del, BOOL *sex, BOOL *founders, double *phe_values, struct chromosomes *chromos, struct selected_options *ops);

/*!
\brief Log the filter settings.
\details
	Write a log of all the filter settings (i.e. timestamp, threshold values, input file paths...) 
	to text file of key-pair values.<br>
	The output file name is a concatonation of \ref selected_options::ldir, 
	\ref selected_options::szRunId and \ref SUFFIX_FILTER_SETTINGS .
\param [in] ops The filter settings.
\returns 1 on success, 0 on failure
*/
int bfilter_write_log(struct selected_options *ops);

#ifdef __cplusplus
}
#endif

#endif // _BFILTER_H_
